<!--

mc-config:{
              type:
                  kv:镜头的外键     ,options:[{k:'',v:''}]}
                  pk:不可枚举的外键      api:{url:'数据地址' method:'post'|'get' params:[] fields:[]}  pkField:'id' pkTextField:'name' limit:10

注意建表时 外键类型一定要选对 否则出不来
@mc-change 监听手动切换下拉框
#option 下拉条码
:mc-option-disabled = "function(item){return false;}"
-->

<template>
  <el-select @focus="focusMe" ref="elSelect" @blur="blurMe" class="mc-remote-select" @change="selectChange" v-model="selectValue" :loading="loading" v-bind="$attrs" v-on="$listeners" filterable remote :remote-method="remoteSearch" @visible-change="selectClick"
  @hook:mounted="cancalReadOnly">
    <template #prefix><i :class="mcPrefixIcon || 'el-icon-search'"></i></template>
    <slot/>
    <el-option v-for="(item,idx) in remoteOptions" :key="item.k" :label="item.v" :value="item.k" :disabled="getOptionDisabled(item)">
      <slot name="option" :row="item.row" :label="item.v" :value="item.k" :vue="vueIns"></slot>
    </el-option>
  </el-select>
</template>

<script>
import McCommon from "./McCommon";
import McDialog from "./McDialog.vue"

export default {
  name: 'mc-remote-select',
  data () {
    return {
      rendered:false,
      remoteOptions:[],
      loading:false,
      triggerWatch:true,
      vueIns:this,
      oldVal:null
    }
  },

  props:[
  'mcConfig','value',
    'mcv1','mcv2','mcv3','mcv4','mcv5','mcv6','mcv7','mcv8','mcv9','mcv10',
    'mcv11','mcv12','mcv13','mcv14','mcv15','mcv16','mcv17','mcv18','mcv19','mcv20',
    'mcPrefixIcon','mcOptionDisabled'
  ],
  components:{
    McDialog
  },
  computed:{
      selectValue:{
        get:function (){
          return this.value;
        },
        set:function (v){
          this.$emit("input",v);
        }
      }
    },
    watch:{
        selectValue(val,oldVal){
          this.oldValue = oldVal;
          if(this.triggerWatch){
              if(!this.emptyValue(val)){
                  this.remoteSearch(null,val);
              }
           }
        }
    },
  updated:function(){
    McCommon.util.refreshDragEvent(this)
  },
  mounted () {
      if(!this.emptyValue(this.value)){//空值没必要查询后台
        this.remoteSearch(null,this.value);
      }
      this.$nextTick(() => {
        //最后一个参数 可以让事件冒泡 也就是所有的组件滚动条都能监听
        McCommon.util.addScrollEvent(this.scrollEvent)
      })
  },
  destroyed(){
    McCommon.util.removeScrollEvent(this.scrollEvent)
  },
  methods:{
    //修复iOS下软键盘无法唤醒问题
    cancalReadOnly(onOff){
      this.$nextTick(() => {
        if (!onOff) {
          const { elSelect } = this.$refs;
          const input = elSelect.$el.querySelector('.el-input__inner');
          input.removeAttribute('readonly');
        }
      });
    },
    getOptionDisabled(item){
      if(this.mcOptionDisabled){
        return this.mcOptionDisabled({row:item});
      }
      return false;
    },
    //优化性能 空的数据没必要查询
    emptyValue(val){
      var result =  val === null || val === '' || typeof val ==='undefined'
      if(result){
        return true;
      }
      if(val && Array.isArray(val)){
        if(val.length<=0){
          return true;
        }
      }
      return false;
    },
    focus(){
      this.$nextTick(()=>{
        this.$refs.elSelect.focus();
      })
    },
    blur(){
      this.$nextTick(()=>{
        this.$refs.elSelect.blur();
      })
    },
    focusMe(e){
      if(window.iframeUi) {
        try {window.iframeUi.fastKey._triggerClickElem(e);}catch(e1) {}
      }
    },
    scrollEvent:function (e){
      if(!this.rendered){
        this.rendered = this.remoteSearch(null,this.selectValue);//反正是设计器阶段 无所谓的 能出来数据就行
      }else {
        //这里必须放 不然还取消不了事件呢
        McCommon.util.removeScrollEvent(this.scrollEvent)
      }
    },
      selectClick(visible){
          this.cancalReadOnly(visible);
          if(visible){
              this.remoteSearch(null,null)
          }
      },
      selectChange(val){
        this.notTriggerWatch(val);
        var row = this.emitMcChange('click',val);
        this.$emit("change",{value:val,row:row,originValue:this.selectValue,oldValue:this.oldValue})
      },
      emitMcChange(type,val){
          var row = null;
          if(this.remoteOptions){
            for(var i=0;i<this.remoteOptions.length;i++){
              var option = this.remoteOptions[i];
              if(val===option.k){
                row = option.row;
                break;
              }
            }
          }
          //vue事件 多选就不能这么搞了 TODO row就应该是数组了
        this.$nextTick(()=>{//经常值变了 外部绑定的还没变化
          //参考了element源码 dispatch触发事件
          this.$refs.elSelect.dispatch('ElFormItem', 'el.form.change', [val]);
          //即将废弃originValue
          this.$emit("mc-change",{trigger:type,value:val,row:row,originValue:this.selectValue,oldValue:this.oldValue})
        })
        return row;
      },
      notTriggerWatch(val){
        this.triggerWatch = false;
        this.$nextTick(() => {
          this.triggerWatch = true;
        });
      },
      remoteSearch(mcKeyword,selectValue){
        if(!McCommon.util.isInWindowView(this.$el)){
          return false;
        }
        this.rendered = true;
        //一定要解绑 当组件被渲染过一次时 滚动监听就不再需要了 懒加载过了 还滚动啥
        McCommon.util.removeScrollEvent(this.scrollEvent)
          var request = this.$magicaltool.request;
          var _t = this;
          if(this.mcConfig){
            var type = this.mcConfig.type;
            //字典项 就比较简单 固定的 初始化一次
            if(type=='pk'){
                  var url = this.mcConfig.api.url;
                  if(url){
                      var method = this.mcConfig.api.method||'post';
                      var limit = this.mcConfig.api.limit||20;
                      if(window.iframeUi){
                        limit = 1;
                      }
                      var param = {};
                      var ncv = request.util.collectMcNameCompareValue(this);
                      var queryByValue = false;
                      if(request.util.isMcQueryUrl(url) || request.util.isContentTypeJson(this.mcConfig.api.contentType)){
                          param = request.util.paramsTomMcQuery(ncv ||this.mcConfig.api.params);
                          if(this.mcConfig.api.fields && this.mcConfig.api.fields.length>0){
                              param.fields = this.mcConfig.api.fields
                          }
                          url += url.indexOf("?")!=-1 ? "&" : "?";
                          //智能搜索 like
                          if(mcKeyword){
                              param.param[this.mcConfig.pkTextField] = mcKeyword;
                              param.condition[this.mcConfig.pkTextField] = "like";
                              url += "limit="+limit;
                          }else{
                              //如果刚开始有值 v-model 就要定点查询了
                              if(selectValue!==0&&selectValue){//有值就别加限制条数
                                  param.param[this.mcConfig.pkField] = selectValue;//加个外键查询
                                  if(Array.isArray(selectValue)){
                                    if(selectValue.length<=0){
                                      return;//空数组 就没必要查询了
                                    }
                                    param.condition[this.mcConfig.pkField] = "in";
                                  }
                                  queryByValue = true;
                              }else {
                                url += "limit="+limit;
                              }
                          }
                          param.order = request.util.mcQueryOrder(this.mcConfig.api.orders);
                      }else{
                          param = request.util.paramsToJson(ncv ||this.mcConfig.api.params);
                          param.mcKeyword=mcKeyword;//加个关键词入参
                          param.limit = limit;//加个关键词入参
                      }
                      this.loading = true;
                      request.axios({cache:true,contentType:this.mcConfig.api.contentType,$vue:this,url:url,method:method,param:param}).then(function(res){
                          _t.loading = false;
                          //不支持emit方法内的await 无法阻塞 所以内部出现axios 不会等待 用户自行处理options吧
                          _t.$emit("before-render-data",{res:res,options:_t.remoteOptions});
                          var list = res.data;
                          if(list){
                             var results = [];
                             var judgeResults = [];
                             if(list){
                                var vtype = typeof _t.selectValue;
                                if(Array.isArray(_t.selectValue)&& _t.selectValue.length>0){
                                  vtype = typeof _t.selectValue[0];//如果是数组 多选的 取数组里第一个看看什么类型
                                }
                                for(var n=0;n<list.length;n++){
                                    var item = list[n];
                                    var k = item[_t.mcConfig.pkField];
                                    if(typeof k === 'undefined' || k==""){
                                      console.warn("警告："+url+"返回数据缺少字段"+_t.mcConfig.pkField);
                                      continue;
                                    }
                                    //自动兼容下 用户配置错误类型
                                    if(typeof k !== vtype){//类型不同 帮用户智能转换
                                      console.warn("警告："+url+"返回数据主键值与绑定的默认值类型不匹配，请确保参数类型一致，已经为您尝试兼容")
                                      if(vtype==='number'){
                                        if(isNaN(k)){//非数字
                                          console.error("警告："+url+"返回数据主键值"+k+"与绑定数值number类型"+_t.selectValue+"不匹配,且无法帮助您转换，请检测是否存在字符串转数字，为您自动忽略该值选择状态"+_t.mcConfig.pkField)
                                          continue;
                                        }
                                        try {
                                          k = Number(k);
                                        }catch (e){
                                          console.log(e)
                                          k = item[_t.mcConfig.pkField];
                                        }
                                      }else if(vtype === 'string'){
                                        k = k+"";
                                      }
                                    }
                                    results.push({k:k,v:item[_t.mcConfig.pkTextField],row:item});
                                    judgeResults.push({k:item[_t.mcConfig.pkField],v:item[_t.mcConfig.pkTextField],row:item});
                                }
                             }
                             _t.remoteOptions = results;
//                             _t.assistJudge(judgeResults);
                             _t.$emit("after-render-data",{res:res,options:_t.remoteOptions});
                             /*if(queryByValue){//这个抛出来并不好 经常要多一道判断
                               _t.emitMcChange('mount',selectValue)
                             }*/
//                             _t.$forceUpdate();
                          }
                       })
                  }
            }else if(type=='kv' && this.mcConfig.options){
                this.remoteOptions = this.mcConfig.options;
            }
          }

          return true;
      },
      /*assistJudge(judgeResults){
        //辅助
        if(this.selectValue || this.selectValue===0){
          var jsType = typeof this.selectValue;
          var list = judgeResults;
          if(list && list.length>0){
            var optionType = typeof list[0].k;
            if(jsType !== optionType){
              console.warn("一级级联下拉框渲染异常,检测到级联下拉框的数据类型与绑定接口返回的类型不一致,请处理使两者类型一致方可正常显示友好值："+this.selectValue+"期望类型"+jsType+","+list[0].k+"实际类型"+optionType);
            }
          }
        }
      },*/
      //获取选中的选项
      apiGetCheckedOption(){
          var val = this.selectValue;
          if(typeof val!='undefined' && val!==null){
            if(Array.isArray(val)){
              if(this.remoteOptions){
                  var arr = [];
                  for(var i=0;i<this.remoteOptions.length;i++){
                    var option = this.remoteOptions[i];
                    for(var j=0;j<val.length;j++){
                      if(option.k+""===val[j]+""){
                        arr.push(option);
                        break;
                      }
                    }
                  }
                  return arr;
              }
            }else {
              if(this.remoteOptions){
                for(var i=0;i<this.remoteOptions.length;i++){
                  var option = this.remoteOptions[i];
                  if(option.k+""===val+""){
                    return option;
                  }
                }
              }
            }
          }
      },
      blurMe(event){
        //参考了element源码 dispatch触发事件
        var val = this.selectValue;
        if(val===null){
          val = val+"";
        }
        this.$refs.elSelect.dispatch('ElFormItem', 'el.form.blur', [val]);
      }
  }
}
</script>

<style lang="scss">
  .mc-remote-select{
    .el-input__prefix{
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      i{
        margin-left: 4px;
      }
    }
  }
  .el-select-dropdown.el-popper{
    /*让弹出的下拉高自适应*/
    .el-select-dropdown__item{
      height: unset;
      min-height:34px;
    }
    /*当下拉框在页面底部时 会因为动态渲染内部导致被遮挡 固定下高度就不会了*/
    min-height:260px;
  }
  /*element的select下拉框在移动端需要点击2次才选中*/
  .el-scrollbar {
    .el-scrollbar__bar {
        opacity: 1 !important;
    }
  }
</style>
